package com.warm.orm.eq.sys.agent;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.easy.query.api.proxy.client.EasyEntityQuery;
import com.easy.query.api.proxy.entity.select.EntityQueryable;
import com.easy.query.api4j.extension.SQL4JFunc;
import com.easy.query.core.basic.api.select.Query;
import com.easy.query.solon.annotation.Db;
import com.warm.core.utils.text.Convert;
import com.warm.datascope.annotaion.DataScope;
import com.warm.orm.domain.sys.SysDept;
import com.warm.orm.domain.sys.SysRoleDept;
import com.warm.orm.domain.sys.SysUser;
import com.warm.orm.domain.sys.proxy.SysDeptProxy;
import com.warm.system.api.orm.agent.SysDeptAgent;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;

import java.util.List;

/**
 * 部门管理 数据层 orm代理类
 *
 * @author warm
 */
@Component
public class SysDeptAgentImpl implements SysDeptAgent {

    @Db
    private EasyEntityQuery easyEntityQuery;

    /**
     * 查询部门是否存在用户
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public int checkDeptExistUser(Long deptId) {
        return this.easyEntityQuery.queryable(SysUser.class).where(t -> t.deptId().eq(deptId)).intCount();
    }

    /**
     * 校验部门名称是否唯一
     *
     * @param deptName 部门名称
     * @param parentId 父部门ID
     * @return 结果
     */
    @Override
    public SysDept checkDeptNameUnique(String deptName, Long parentId) {
        return this.easyEntityQuery
                .queryable(SysDept.class)
                .where(t -> {
                    t.deptName().eq(deptName);
                    t.parentId().eq(parentId);
                })
                .firstOrNull();
    }

    /**
     * 删除部门管理信息
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public int deleteDeptById(Long deptId) {
        return (int) this.easyEntityQuery.deletable(SysDept.class).whereById(deptId).executeRows();
    }

    /**
     * 是否存在子节点
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public int hasChildByDeptId(Long deptId) {
        return this.easyEntityQuery
                .queryable(SysDept.class)
                .where(t -> t.parentId().eq(deptId))
                .intCount();
    }

    /**
     * 新增部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public int insertDept(SysDept dept) {
        return (int) this.easyEntityQuery.insertable(dept).executeRows();
    }

    /**
     * 根据ID查询所有子部门
     *
     * @param deptId 部门ID
     * @return 部门列表
     */
    @Override
    public List<SysDept> selectChildrenDeptById(Long deptId) {
        return this.easyEntityQuery
                // from sys_dept
                .queryable(SysDept.class)
                // where find_in_set(#{deptId}, ancestors)
                .where(t -> t.expression().sql("FIND_IN_SET({0}, {1})", c -> {
                    c.value(deptId);
                    c.expression(t.ancestors());
                }))
                // select *
                .toList();
    }

    /**
     * 根据部门ID查询信息
     *
     * @param deptId 部门ID
     * @return 部门信息
     */
    @Override
    public SysDept selectDeptById(Long deptId) {
        return this.easyEntityQuery.queryable(SysDept.class).whereById(deptId).firstOrNull();
    }

    /**
     * 查询部门管理数据
     *
     * @param dept 部门信息
     * @return 部门信息集合
     */
    @Override
    @DataScope(deptAlias = "d")
    public List<SysDept> selectDeptList(SysDept dept) {
        return this.buildQuery(dept).toList();
    }

    private EntityQueryable<SysDeptProxy, SysDept> buildQuery(SysDept dept) {
        return this.easyEntityQuery
                .queryable(SysDept.class)
                // AND dept_id = #{deptId}
                // AND parent_id = #{parentId}
                // AND dept_name like concat('%', #{deptName}, '%')
                // AND status = #{status}
                .where(t -> {
                    t.deptId().eq(ObjUtil.isNotNull(dept.getDeptId()), dept.getDeptId());
                    t.parentId().eq(ObjUtil.isNotNull(dept.getParentId()), dept.getParentId());
                    t.deptName().like(StrUtil.isNotBlank(dept.getDeptName()), dept.getDeptName());
                    t.status().eq(StrUtil.isNotBlank(dept.getStatus()), dept.getStatus());
                })
                // order by d.parent_id, d.order_num
                .orderBy(t -> t.parentId())
                .orderBy(t -> t.orderNum());
    }

    /**
     * 根据角色ID查询部门树信息
     *
     * @param roleId            角色ID
     * @param deptCheckStrictly 部门树选择项是否关联显示
     * @return 选中部门列表
     */
    @Override
    public List<Long> selectDeptListByRoleId(Long roleId, boolean deptCheckStrictly) {
        return this.buildQueryByRoleId(roleId, deptCheckStrictly).toList();
    }

    private Query<Long> buildQueryByRoleId(Long roleId, boolean deptCheckStrictly) {
        return this.easyEntityQuery
                // from sys_dept d
                .queryable(SysDept.class)
                // left join sys_role_dept rd on d.dept_id = rd.dept_id
                .leftJoin(SysRoleDept.class, (t, t1) -> t1.deptId().eq(t.deptId()))
                .where((t, t1) -> {
                    // rd.role_id = #{roleId}
                    t1.roleId().eq(roleId);
                    // and d.dept_id not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.dept_id =
                    //            rd.dept_id and rd.role_id = #{roleId})
                    t.deptId().notIn(deptCheckStrictly, this.easyEntityQuery
                            .queryable(SysDept.class)
                            .innerJoin(SysRoleDept.class, (d, d1) -> {
                                d1.deptId().eq(d.deptId());
                                d1.roleId().eq(roleId);
                            })
                            .selectColumn((d, d1) -> d.parentId().setPropertyType(Long.class))
                    );
                })
                .selectColumn((t, t1) -> t.deptId().setPropertyType(Long.class));
    }

    /**
     * 根据ID查询所有子部门（正常状态）
     *
     * @param deptId 部门ID
     * @return 子部门数
     */
    @Override
    public int selectNormalChildrenDeptById(Long deptId) {
        return this.easyEntityQuery
                .queryable(SysDept.class)
                // where status = 0
                //   and del_flag = '0'
                //   and find_in_set(#{deptId}, ancestors)
                .where(t -> {
                    t.status().eq("0");
                    t.expression().sql("FIND_IN_SET({0}, {1})", c -> {
                        c.value(deptId);
                        c.expression(t.ancestors());
                    });
                })
                // select count(*)
                .intCount();
    }

    /**
     * 修改部门信息
     *
     * @param dept 部门信息
     * @return 结果
     */
    @Override
    public int updateDept(SysDept dept) {
        return (int) this.easyEntityQuery.updatable(dept).executeRows();
    }

    /**
     * 修改子元素关系
     *
     * @param depts 子元素
     * @return 结果
     */
    @Override
    public int updateDeptChildren(List<SysDept> depts) {
        int updated = 0;
        for (int i = 0; i < depts.size(); i++) {
            SysDept bean = depts.get(i);
            updated += this.easyEntityQuery
                    .updatable(SysDept.class)
                    .setColumns(s -> s.ancestors().set(bean.getAncestors()))
                    .whereById(bean.getDeptId())
                    .executeRows();
        }

        return updated;
    }

    /**
     * 修改所在部门正常状态
     *
     * @param deptIds 部门ID组
     */
    @Override
    public void updateDeptStatusNormal(Long[] deptIds) {
        this.easyEntityQuery
                .updatable(SysDept.class)
                .setColumns(c -> c.status().set("0"))
                .where(t -> t.deptId().in(deptIds))
                .executeRows();
    }
}
